import {promises as fs} from 'fs';
import path from 'path';
import {IEncryptor} from "../types";

/**
 * 文件系统工具类
 */
export class FileSystem {
    /**
     * 确保目录存在，如果不存在则创建
     * @param dirPath 目录路径
     */
    static async ensureDir(dirPath: string): Promise<void> {
        try {
            await fs.access(dirPath);
        } catch {
            await fs.mkdir(dirPath, {recursive: true});
        }
    }

    /**
     * 读取文件内容
     * @param filePath 文件路径
     * @param crypto 加密实例（可选）
     */
    static async readFile(filePath: string, crypto?: IEncryptor): Promise<string> {
        try {
            let content = await fs.readFile(filePath, 'utf-8');

            // 如果提供了加密实例，尝试解密
            if (crypto) {
                try {
                    content = crypto.decrypt(content);
                } catch (error) {
                    throw new Error(`Failed to decrypt file ${filePath}: ${(error as Error).message}`);
                }
            }

            return content;
        } catch (error) {
            if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
                throw new Error(`File not found: ${filePath}`);
            }
            throw error;
        }
    }

    /**
     * 写入文件内容
     * @param filePath 文件路径
     * @param content 内容
     * @param crypto 加密实例（可选）
     */
    static async writeFile(filePath: string, content: string, crypto?: IEncryptor): Promise<void> {
        // 如果提供了加密实例，加密内容
        if (crypto) {
            try {
                content = crypto.encrypt(content);
            } catch (error) {
                throw new Error(`Failed to encrypt content for ${filePath}: ${(error as Error).message}`);
            }
        }

        await FileSystem.ensureDir(path.dirname(filePath));
        await fs.writeFile(filePath, content, 'utf-8');
    }

    /**
     * 读取JSON文件
     * @param filePath 文件路径
     * @param crypto 加密实例（可选）
     */
    static async readJson<T>(filePath: string, crypto?: IEncryptor): Promise<T> {
        const content = await FileSystem.readFile(filePath, crypto);
        return JSON.parse(content) as T;
    }

    /**
     * 写入JSON文件
     * @param filePath 文件路径
     * @param data 数据
     * @param crypto 加密实例（可选）
     */
    static async writeJson<T>(filePath: string, data: T, crypto?: IEncryptor): Promise<void> {
        const content = JSON.stringify(data, null, 2);
        await FileSystem.writeFile(filePath, content, crypto);
    }

    /**
     * 检查文件是否存在
     * @param filePath 文件路径
     */
    static async exists(filePath: string): Promise<boolean> {
        try {
            await fs.access(filePath);
            return true;
        } catch {
            return false;
        }
    }

    /**
     * 删除文件
     * @param filePath 文件路径
     */
    static async removeFile(filePath: string): Promise<void> {
        try {
            await fs.unlink(filePath);
        } catch (error) {
            if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {
                throw error;
            }
        }
    }
}
